using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Collections.Generic;
using System.Collections;
using System.Drawing;
using BuildingBasicDomain;

using MVCFramework.Models;
using MVCFramework.Presenter;

using CommonTypes.Events;
using CCSDomain.OpenGL.Drawer;



namespace MVCFramework.View
{

    //CODE DUBLICATION with ViewFrorm 
    [System.Diagnostics.DebuggerDisplay("Related to presenter {_presenter .Id} And Model {_model.Id}")]
    public partial class UserControlView : UserControl,IViewUserControl 
    {
        public UserControlView()
        {
            InitializeComponent();
        }

        # region " Private Declaration "
        ContextMenu contextMenu;

        private bool isActive;
        public bool IsActive
        {
            get
            {
                return isActive;
            }
            set
            {
                isActive = value;
            }
        }


        protected IModel _model;
        private IPresenter _presenter;

        public IPresenter Presenter
        {
            get { return _presenter; }
            set { _presenter = value; }
        }

        protected ViewState _viewState;
        public ViewState ViewState
        {
            set
            {
                _viewState = value;

                if (OnStateChanged != null)
                    OnStateChanged(this, new EventArgs());
            }
            get
            {
                return _viewState;
            }
        }

        private IViewSelector _selector;
        protected IViewSelector ViewSelector
        {
            set { _selector = value; }
            get { return _selector; }
        }

        #endregion
        
        public void SetUpUserControlView2(IModel _model, IPresenter _presenter, string id) 
        {
            SetUpUserControlView2(_model, _presenter);
            Id = id;
         //   InitializeComponent();
        }
        public void SetUpUserControlView2(IModel _model, IPresenter _presenter)
        {

            this._model = _model;
            this._presenter = _presenter;


            InitializeViewState();
            if (_viewState != null)
                _viewState.Model = _model;


          //  InitializeComponent();
            InitializeViews();
            double max = GetMaxDimension(_model);

            SetOpenGLWorldBounds(max);

            this.OnViewActivated += new EventHandler<EventArgs>(_presenter.SetSelectedView);

            glDrawer1.OnMouseDownAction += new CCSDomain.OpenGL.Drawer.GLDrawer.ActionActionHandler(DrawerDownHandler);
            glDrawer1.OnMouseMoveAction += new CCSDomain.OpenGL.Drawer.GLDrawer.ActionActionHandler(DrawerMoveHandler);
            glDrawer1.OnMouseUpAction += new CCSDomain.OpenGL.Drawer.GLDrawer.ActionActionHandler
(DrawerUpHandler);
            glDrawer1.ViewState = CCSDomain.OpenGL.Drawer.GLDrawer.ViewStates.ContiniousSelect;
            glDrawer1.ViewMode = CCSDomain.OpenGL.Drawer.GLDrawer.ViewModes.Perspective;

            glDrawer1.ViewState = GLDrawer.ViewStates.ContiniousSelect;
            glDrawer1.SetupTransparency();
            glDrawer1.EnableLights = true;
            glDrawer1.EnableTrasparency = true;
        }

        private void SetOpenGLWorldBounds(double max)
        {
            glDrawer1.SetWorldBounds(-max / 1.4f, max / 1.4f, -max / 1.4f, max / 1.4f, max / 1.4f, -max / 1.4f);
         //   glDrawer1.SetWorldBounds(-max / 1.4f, max / 1.4f, -max / 1.4f, max / 1.4f, max / 1.4f, -max / 1.4f);
        }
        private void InitializeViews()
        {
            SetUpIViewSelector();
            glDrawer1.ShowAxis = true;
            glDrawer1.DrawScene += new CCSDomain.OpenGL.Drawer.GLDrawer.DrawSceneDelegate(DrawScene1);
            glDrawer1.LockKeyShortcuts = true;

            glDrawer1.OnSelectArrayObjects += new CCSDomain.OpenGL.Drawer.GLDrawer.SelectionArrayDelegate(OnMouseSelectDown);       
           
            # region glDrawer mouse event listener "

            glDrawer1.ViewState = CCSDomain.OpenGL.Drawer.GLDrawer.ViewStates.MoveElement;
           this.OnViewMouseDown += new ActionHandler(((MVCFramework .IViewActionListener ) Presenter).MouseDownHandler);
            this.OnViewMouseMove += new ActionHandler(((MVCFramework .IViewActionListener ) Presenter).MouseMoveHandler);
            this.OnViewMouseUp  += new ActionHandler(((MVCFramework .IViewActionListener ) Presenter).MouseUpHandler);
            
            #endregion 
        }

        public event EventHandler <EventArgs> OnViewActivated;
        public event EventHandler<EventArgs> OnStateChanged;

        private Id<IView> _id;
        public Id<IView> Id
        {
            get
            {
                if (_id.IsEmpty) return "UserControl";
                return _id;
            }
            set
            {
                _id = value;
            }
        }

        public delegate double MaxCalcFunction(IModel model);
        private MaxCalcFunction CurrentStrategy;
        public void SetMaxSpaceCalulationStrategy(MaxCalcFunction stategy)
        {
            CurrentStrategy = stategy;
            SetOpenGLWorldBounds(GetMaxDimension(this._model));
            Update();
        }
        protected virtual double GetMaxDimension(IModel _model)
        {
            if (CurrentStrategy != null)
            {
                return CurrentStrategy(_model);
            }
            else return 1000;

        }

        protected virtual void InitializeViewState()
        {
            _viewState = new EmtyState();
        }

		protected virtual void DrawerDownHandler(Object sender, GLDrawer.DrawerActionEventArgs e)
		{
            if (OnViewMouseDown != null)
            {
                ArrayList _selectedObjects = _selector.getSelectedObjects(e.Selected );
                e.Worldcoord =_viewState.getPoint(e.Worldcoord );
                ActionEventArgs args =  new ActionEventArgs (_selectedObjects,e.Coordinates );
                args.Selected = e.ModelSelected;
                args.Worldcoord = e.Worldcoord ;
                OnViewMouseDown(this,args );
            }
		}
        protected virtual void DrawerMoveHandler(Object sender, GLDrawer.DrawerActionEventArgs e)
        {
            if (OnViewMouseMove  != null)
            {

                ArrayList _selectedObjects = _selector.getSelectedObjects(e.Selected);
                ActionEventArgs args = new ActionEventArgs(_selectedObjects,e.Coordinates);
                args .Worldcoord = e.Worldcoord ;
                OnViewMouseMove(this,args);

            }
        }
        protected virtual void DrawerUpHandler(Object sender, GLDrawer.DrawerActionEventArgs e)
        {
            if (OnViewMouseUp != null)
            {
                ArrayList _selectedObjects = _selector.getSelectedObjects(e.Selected);
                e.Worldcoord =_viewState.getPoint(e.Worldcoord);
                ActionEventArgs args = new ActionEventArgs(_selectedObjects, e.Coordinates);
                args.Worldcoord = e.Worldcoord;
                OnViewMouseUp (this, args );
            }
        }

        # region " IDrawable Implemantation "

        public event ActionHandler OnViewMouseDown;

        public event ActionHandler OnViewMouseMove;

        public event ActionHandler OnViewMouseUp;


        public void drawLine(Object point1, Object point2)
        {
            if (point1 is IPoint && point2 is IPoint)
            {
                BuildingBasicDomain.IPoint _point1 = point1 as BuildingBasicDomain.IPoint;
                BuildingBasicDomain.IPoint _point2 = point2 as BuildingBasicDomain.IPoint;

                if (point1 != null && point2 != null)
                {
                //    XorLine((int)_point1.X, (int)_point1.Y, (int)_point2.X, (int)_point2.Y);
                }
            }
        }


        public void drawElasRectangle()
        {

        }

        # endregion 

        protected virtual void SetUpIViewSelector()
        {
            this.ViewSelector = new DefultViewSelector(_model);
        }

        private void OnMouseSelectDown(uint[] objectArray) { }
        
        private void DrawScene1()
        {
            if(_viewState != null)
                 _viewState.DispalyView();
        }
 
        public void SetDrawerState(CCSDomain.OpenGL.Drawer.GLDrawer.ViewStates state)
        {
            glDrawer1.ViewState = state;
        }

        public  void ZoomIn()
        {
            glDrawer1.ZoomIn();
        }

        public  void ZoomOut()
        {
            glDrawer1.ZoomOut();
        }

        public  void Rotate()
        {
            glDrawer1.ViewState = CCSDomain.OpenGL.Drawer.GLDrawer.ViewStates.Rotate;
        }

        public  void MoveGL()
        {
            glDrawer1.ViewState = CCSDomain.OpenGL.Drawer.GLDrawer.ViewStates.Move;
        }

        private void this_Load(object sender, EventArgs e)
        {

        }

        public void drawLine(object   line)
        {
            if (line is ILine)
            {
                _viewState.drawLine(line as ILine );
            }
        }

        public new void  Update()
        {
            DrawScene1();
            glDrawer1.Invalidate();
            this.Invalidate();
        }

        private void ViewActivationHAndler()
        {
            if (OnViewActivated != null)
                OnViewActivated(this, null);
            this.IsActive = true;
        }

        private void ContextMenuParsing(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {

                if (contextMenu == null)
                    InitContextMenu();
                if (contextMenu != null)
                {
                    contextMenu.Show(this, new System.Drawing.Point(e.X, e.Y));
                    contextMenu = null;
                }

                if (contextMenu == null)
                {
                    glDrawer1.PopContextMenu(e);
                }

            }
        }

        # region " Menu Handling "
        private void InitContextMenu()
        {

            ArrayList menu = Presenter.ParseContextMenu();
            if (menu != null)
            {
                contextMenu = new ContextMenu();
                foreach (MVCFramework .Menus .IMenuCommand command in menu)
                {
                  //  EventHandler commandHandler = new EventHandler(delegate(object sender, EventArgs args) { command.Execute(); });     WHY THIS FAILS STUPID MSOFT
                    MenuItem item = new MenuItem(command.MenuCaption,MenuHandler2);
                   
                    contextMenu.MenuItems.Add(item);
                }
            }
        }

        private void MenuHandler(object sender, EventArgs args)
        {
        }

        private void MenuHandler2(object sender, EventArgs  args)
        {
            Presenter.DispatchMenuEvent((sender as MenuItem).Text);
        }  

        #endregion

        #region IDrawable Members

        public void drawLine(ILine line)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void drawPoint(IPoint point)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void drawPlane(IArea plane)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void drawLine(IPoint point1, IPoint point2)
        {
           // throw new Exception("The method or operation is not implemented.");
        }

        public void drawPlane(ILine line, IPoint point)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void drawPlane(IPoint point1, IPoint point2, IPoint point3)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void drawRect(IPoint point1, IPoint point2)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IViewForm Members

        public event EventHandler<EventArgs> OnViewDeActivated;

        #endregion

        #region IView Members


        public void AddFilter(MVCFramework.Models.Filters.IFilter filter)
        {
            throw new NotImplementedException ();
        }

        #endregion

        #region IViewForm Members Rotation


        public void ViewTop()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Top;
        }

        public void ViewBottom()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Bottom;
        }

        public void ViewLeft()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Left;
        }

        public void ViewRight()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Right;
        }

        public void ViewPerspective()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Perspective;
        }

        public void ViewFront()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Front;
        }

        public void ViewBack()
        {
            glDrawer1.ViewMode = GLDrawer.ViewModes.Back;
        }

        public void SetRotationAngles(double rx, double ry, double rz)
        {
            glDrawer1.SetRotation(rx, ry, rz);
        }

        public void SetViewState(Type viewState)
        {
            ViewState = Activator.CreateInstance(viewState) as ViewState ;
            ViewState.Model = this._model;
        }

        public void SetViewState(Type viewState, Type[] argTypes, object[] args, string[] argNames)
        {
            object _object = BuildingBasicDomain.DefaultFactoryBase.CreateInstance(viewState, argTypes, args, argNames);
           if (_object != null)
               ViewState = _object as ViewState;
           else throw new MVCFramework.ModelExeption("View failed to set ist's state to " + viewState .Name ); 
            ViewState.Model = this._model;
        }


        #endregion

        public override string ToString()
        {
            return "View id :" + Id;
        }

        #region IViewUserControl Members


        public void Activate()
        {
            this.Activate();
        }

        #endregion

        #region IViewUserControl Members

        Form midiconatiner;

        public Form MdiParent
        {
            get
            {
                return this.midiconatiner as Form;
            }
            set
            {
                midiconatiner = value;
            }
        }

        #endregion

    }
}
